package coll

import (
	"errors"
	"fmt"
	"gitee.com/hongzhaomin/hzm-common-go/assert"
	"gitee.com/hongzhaomin/hzm-common-go/streams"
)

// List 切片的别名
type List[E comparable] []E

// NewList 创建list集合
func NewList[E comparable]() *List[E] {
	return NewListWithCap[E](0)
}

// NewListWithCap 创建list集合, 可设置 cap容量
func NewListWithCap[E comparable](cap int) *List[E] {
	list := make([]E, 0, cap)
	return (*List[E])(&list)
}

// OfList 将切片slice转成*List[E]
func OfList[E comparable](slice []E) *List[E] {
	newList := NewListWithCap[E](len(slice))
	newList.AddAll(slice)
	return newList
}

// NewList4Set 根据keyMap创建*List[E]
func NewList4Set[E comparable](keyMap map[E]struct{}) *List[E] {
	list := NewListWithCap[E](len(keyMap))
	for key := range keyMap {
		list.Add(key)
	}
	return list
}

// ToSet list转set
func (my *List[E]) ToSet() *Set[E] {
	return NewSet4Slice(*my)
}

// Stream 将List转化为Stream流处理
func (my *List[E]) Stream() streams.Stream[E] {
	return streams.OfSlice(*my)
}

// Get 返回切片索引index处的元素
func (my *List[E]) Get(index int) E {
	my.rangCheck(index)
	list := *my
	return list[index]
}

// Size 返回切片的大小
func (my *List[E]) Size() int {
	return len(*my)
}

// Contains 返回切片是否包含元素ele的布尔值
func (my *List[E]) Contains(ele E) bool {
	return my.IndexOf(ele) >= 0
}

// IsEmpty 返回切片是否为空的布尔值
func (my *List[E]) IsEmpty() bool {
	return my.Size() == 0
}

// IndexOf 返回ele对应切片最近一个元素的索引下标，没有则返回-1
func (my *List[E]) IndexOf(ele E) int {
	for i, e := range *my {
		if ele == e {
			return i
		}
	}
	return -1
}

// LastIndexOf 返回ele对应切片最后一个元素的索引下标，没有则返回-1
func (my *List[E]) LastIndexOf(ele E) int {
	list := *my
	for i := my.Size() - 1; i >= 0; i-- {
		if ele == list[i] {
			return i
		}
	}
	return -1
}

// Lists 返回切片的子切片的切片（子切片大小为subSize）
func (my *List[E]) Lists(subSize int) [][]E {
	return Page(*my, subSize)
}

// ForEach 切片的循环操作
func (my *List[E]) ForEach(action func(t E)) {
	assert.NonNil(action, "action func must not nil")
	for _, e := range *my {
		action(e)
	}
}

// Add 在切片末尾添加一个元素ele
func (my *List[E]) Add(ele E) {
	*my = append(*my, ele)
}

// AddAt 在切片index索引位置添加一个元素ele
func (my *List[E]) AddAt(index int, ele E) {
	list := *my
	if index == len(list) {
		my.Add(ele)
		return
	}
	my.rangCheck(index)
	list = append(list, ele)
	copy(list[index+1:], list[index:])
	list[index] = ele
	*my = list
}

// AddAll 在切片末尾添加len(eles)个元素eles
func (my *List[E]) AddAll(eles []E) {
	if len(eles) != 0 {
		*my = append(*my, eles...)
	}
}

// AddAllAt 从切片index索引位置开始添加len(eles)个元素eles
func (my *List[E]) AddAllAt(index int, eles []E) {
	if len(eles) == 0 {
		return
	}
	list := *my
	if index == len(list) {
		my.AddAll(eles)
		return
	}
	my.rangCheck(index)
	list = append(list, eles...)
	copy(list[index+len(eles):], list[index:])
	for i, ele := range eles {
		list[index+i] = ele
	}
	*my = list
}

// RemoveAt 删除切片index索引位置的元素
func (my *List[E]) RemoveAt(index int) bool {
	my.rangCheck(index)
	list := *my
	*my = append(list[:index], list[index+1:]...)
	return true
}

// Remove 删除切片中的元素ele
func (my *List[E]) Remove(ele E) bool {
	index := my.IndexOf(ele)
	if index != -1 {
		my.RemoveAt(index)
		return true
	}
	return false
}

// RemoveIf 删除表达式predicate为true的切片中的元素
func (my *List[E]) RemoveIf(predicate func(ele E) bool) {
	list := *my
	size := my.Size()
	r, w := 0, 0
	for ; r < size; r++ {
		if !predicate(list[r]) {
			// 进入判断，则保留
			list[w] = list[r]
			w++
		}
	}
	*my = list[:w]
}

// RemoveAll 删除切片中的元素eles
func (my *List[E]) RemoveAll(eles []E) {
	my.batchRemove(eles, false)
}

// RetainAll 保留切片中的元素eles
func (my *List[E]) RetainAll(eles []E) {
	my.batchRemove(eles, true)
}

// batchRemove 批量处理切片中的元素eles
func (my *List[E]) batchRemove(eles []E, complement bool) {
	my.RemoveIf(func(ele E) bool {
		return !(Contains(eles, ele) == complement)
	})
}

func (my *List[E]) rangCheck(index int) {
	if index < 0 || index > len(*my)-1 {
		msg := fmt.Sprintf("索引越界：index %d, size %d", index, my.Size())
		panic(errors.New(msg))
	}
}
